﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Utility.Data;
using System.Utility.DBMS;

namespace System.Utility.Emailing
{
    public class ActivationLink
    {
        string emailId = string.Empty;
        public ActivationLink(string emailId)
        {
            this.emailId = emailId;
        }

        public string GenerateLink()
        {
            string activatePath = Settings.GetSettingByKey("ActivatePath");
            Guid resquestId = Guid.NewGuid();
            string encryptId = PasswordProtector.Encrypt(resquestId.ToString(), emailId).Replace("+", "").Replace("==", "");
            activatePath += "?requestId=" + encryptId;
            //save it in database
            SaveToDataBae(encryptId, emailId, DateTime.Now, DateTime.Now.AddMinutes(int.Parse(Settings.GetSettingByKey("ExpLength"))));
            return activatePath;
        }


        private void SaveToDataBae(string encryptId, string emailId, DateTime generateTime, DateTime expiryTime)
        {
            DBHelper.ExcuteProc("AddResetLink", new object[] { encryptId, emailId, generateTime, expiryTime });

        }
    }

    public class EnumHelper
    {
        public static T ParseEnum<T>(string value)
        {
            return (T)Enum.Parse(typeof(T), value, true);
        }

        public static T ParseEnum<T>(string value, bool ignoreCase)
        {
            return (T)Enum.Parse(typeof(T), value, ignoreCase);
        }
    }

    public abstract class ContentLoadeBase
    {
        public abstract string LoadContent();

        private bool isBodyHTML = true;
        public virtual bool IsBodyHtml { get { return isBodyHTML; } set { isBodyHTML = value; } }

        private string subject = "You recieved new email";
        public virtual string Subject { get { return subject; } set { subject = value; } }
    }

    public class StandardTemplateContentLoader : ContentLoadeBase
    {
        EmmailTemplate template = null;
        public StandardTemplateContentLoader(string templateid)
        {
            template = EmmailTemplate.GetTemplateById(templateid);
        }

        public override string LoadContent()
        {
            Logger.LogMessage("reading mail content fomr the path :- " + this.template.Path, LogLevel.DEBUG, LogMessageType.ApplicationMessage);
            StreamReader reader = new StreamReader(this.template.Path);
            return reader.ReadToEnd();
        }
    }

    public class EmmailTemplate
    {
        string templateId;
        public string TemplateId
        {
            get { return templateId; }
        }

        string path;
        public string Path
        {
            get { return path; }
        }

        string type;
        public string Type
        {
            get { return type; }
        }

        string subject;
        public string Subject
        {
            get { return subject; }
        }

        static List<EmmailTemplate> templates = null; //new List<EmmailTemplate>();
        private static void LoadAll()
        {
            templates = new List<EmmailTemplate>();
            DataTable dt = new DataTable();
            //foreach (DataRow dr in dt.Rows)
            //{
                EmmailTemplate t = new EmmailTemplate();
                //t.path = dr["TemplatePath"].ToString();  //@"C:\Users\vkgupta\Downloads\HTMLParser\HTMLParser\ConsoleApplication1\Reset.htm";
                //t.templateId = dr["TemplateName"].ToString();// "ApprovalEmail";
                //t.type = dr["EmailType"].ToString();// "ApprovalEmail";
                //t.subject = dr["Subject"].ToString();// "New Request | Pending Approval";

                t.path = @"C:\Users\abudakandi\Downloads\GuessLAB\GuessLAB.UI\Reset.htm";
                t.templateId = "ResetEmail";
                t.type = "ResetEmail";
                t.subject = "Updtae Passowrd Request | Pending";


                templates.Add(t);
            //}
        }

        public static EmmailTemplate GetTemplateById(string templateId)
        {
            if (templates == null || templates.Count == 0)
                LoadAll();
            return templates.Find(p => p.templateId == templateId);
        }
    }

    public delegate void MailContentReplaceEventHandler(object sender, MailContentEventArgs e);

    public class MailContentEventArgs
    {
        public string Content { get; set; }
    }

    public class MailEventArgs : EventArgs
    {
        private MailMessage myMail = null;
        public MailEventArgs(MailMessage myMail)
        { this.myMail = myMail; }

        public MailMessage MyMail { get { return this.myMail; } }
    }

    public delegate void MailEventHandler(object sender, MailEventArgs eventArgs);

    public abstract class EmailerBase
    {
        public EmailerBase()
        {
            // TODO: Complete member initialization
        }

        private MailAddress from;
        private MailAddress to;
        MailMessage myMail = new System.Net.Mail.MailMessage();
        public event MailEventHandler ToMail;
        public event MailEventHandler MailAttachment;

        public void Send()
        {
            try
            {
                SmtpClient mySmtpClient = new SmtpClient(Settings.GetSettingByKey("SmtpClient"));

                if (Settings.GetSettingByKey("CredentialBased") == "true")
                {
                    mySmtpClient.UseDefaultCredentials = false;
                    mySmtpClient.Credentials = new System.Net.NetworkCredential(Settings.GetSettingByKey("NCID"), Settings.GetSettingByKey("NCPWD"));
                }



                mySmtpClient.Port = 587;
                mySmtpClient.EnableSsl = true;

                this.SetSenderInfo();

                myMail.From = from;
                MailEventArgs args = new MailEventArgs(myMail);

                try
                {
                    try
                    {
                        this.SetToInfo(args);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogMessage("Developer code is unable to set the email id to send the email", LogLevel.INFO, LogMessageType.WebMessage);
                        throw new Exception(Constants.ApplicationErrorPrefix + "EG1005");
                    }

                    if (myMail.To == null || myMail.To.Count == 0)
                    {
                        Logger.LogMessage("Developer code is unable to set the email id to send the email", LogLevel.INFO, LogMessageType.WebMessage);
                        throw new Exception(Constants.ApplicationErrorPrefix + "EG1005");
                    }


                    //override email id in case of testing.
                    string[] emailTestingInfo = Settings.GetSettingByKey("EmailTesting").Split('|');
                    if (bool.Parse(emailTestingInfo[0]))
                    {
                        myMail.To.Clear();
                        myMail.To.Add(new MailAddress(emailTestingInfo[1], emailTestingInfo[1]));
                    }


                }
                finally
                {
                    if (myMail.To == null || myMail.To.Count == 0)
                        throw new Exception(Constants.ApplicationErrorPrefix + "EG1004");
                }

                MailAddress replyto = new MailAddress(Settings.GetSettingByKey("ReplyAddress"));
                myMail.ReplyTo = replyto;

                this.OnAttachment(args);

                this.Subject(myMail);
                this.SetBody(myMail);

                try
                {
                    Logger.LogMessage("Targeted emailid to sent the email :-" + myMail.To[0].Address, LogLevel.INFO, LogMessageType.WebMessage);
                }
                catch (Exception ex) { }


                mySmtpClient.Send(myMail);

                Logger.LogMessage("Mail has been sent to " + GetAddress(), LogLevel.INFO, LogMessageType.ApplicationMessage);
            }

            catch (SmtpException sEx)
            {
                Logger.LogMessage("Unable to send mail " + GetAddress(), LogLevel.INFO, LogMessageType.ApplicationMessage);
                Logger.LogException(sEx.Message, sEx, ExceptionLevel.ERROR, LogMessageType.ApplicationMessage);
                throw;

            }
            catch (Exception ex)
            {
                Logger.LogMessage("Unable to send mail to email id  -" + GetAddress(), LogLevel.INFO, LogMessageType.ApplicationMessage);
                Logger.LogException(ex.Message, ex, ExceptionLevel.ERROR, LogMessageType.ApplicationMessage);
                throw;
            }

        }

        private string GetAddress()
        {
            string str = string.Empty;
            foreach (MailAddress address in this.myMail.To)
            {
                str += address + ",";
            }
            return str;
        }

        protected abstract void Subject(MailMessage myMail);
        protected abstract void SetBody(MailMessage myMail);

        protected virtual void SetToInfo(MailEventArgs e)
        {
            if (ToMail != null)
                ToMail(this, e);
            //to = new MailAddress(userId, userId);
        }

        protected virtual void OnAttachment(MailEventArgs e)
        {
            if (MailAttachment != null)
                MailAttachment(this, e);
            //to = new MailAddress(userId, userId);
        }

        protected virtual void SetSenderInfo()
        {
            string[] senderInfo = Settings.GetSettingByKey("Sender").Split('|');
            from = new MailAddress(senderInfo[0], senderInfo[1]);
        }
    }

    public class StandardTemplateEmailer : EmailerBase
    {
        private EmailDataContainer emailDataContainer = null;
        private ContentLoadeBase loader = null;
        public StandardTemplateEmailer(EmailDataContainer emailDataContainer)
        {
            this.emailDataContainer = emailDataContainer;
            this.loader = emailDataContainer.ContentLoadeBase;
        }

        public event MailContentReplaceEventHandler MailContentReplace;

        protected override void Subject(MailMessage myMail)
        {
            string subject = this.loader.Subject;
            myMail.Subject = subject;
        }

        protected override void SetBody(MailMessage myMail)
        {
            myMail.SubjectEncoding = System.Text.Encoding.UTF8;
            string content = this.loader.LoadContent();
            MailContentEventArgs args = new MailContentEventArgs { Content = content };
            this.OnContentReplace(args);
            myMail.Body = args.Content;
            myMail.BodyEncoding = System.Text.Encoding.UTF8;
            myMail.IsBodyHtml = this.loader.IsBodyHtml;
        }

        protected void OnContentReplace(MailContentEventArgs args)
        {
            if (MailContentReplace != null)
                MailContentReplace(this, args);
        }

    }

    public enum ContainerType
    {
        StandardTemplate, PlainContent
    }

    public class EmailDataContainer
    {
        ContainerType containerType = ContainerType.StandardTemplate;
        public ContainerType ContainerType { get { return containerType; } set { containerType = value; } }

        ContentLoadeBase contentLoadeBase = null;
        public ContentLoadeBase ContentLoadeBase { get { return contentLoadeBase; } }

        public EmailDataContainer(ContentLoadeBase contentLoadeBase)
        {
            this.contentLoadeBase = contentLoadeBase;
        }

        public MakerChecker MakerChecker { get; set; }
        public string ToMail { get; set; }
    }

    public class MakerChecker
    {
        public string Source { get; set; }
        public string Destination { get; set; }
        public string Data { get; set; }
        public string Comment { get; set; }
        public string TPath { get; set; }
        public string User { get; set; }
        public string Action { get; set; }
        public string ReasonforRejection { get; set; }
    }


}
